/*
 *  buddy.c
 *
 *  Buddy management
 *
 *  Copyright (C) 2008  Huang Guan
 *
 *  2008-7-12 Created.
 *
 *  Description: This file mainly includes the functions about 
 *
 */

#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#ifdef _WINDOWS
#include <winsock.h>
#include <wininet.h>
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#endif
#include "qqclient.hpp"

#include "debug.hpp"
#include "protocol.hpp"
#include "buddy.hpp"
#include "packetmgr.hpp"

namespace {
//按qq号码进行升序排序
struct buddy_comp:public std::binary_function<qqbuddy*,qqbuddy*,bool>{
	bool operator() (const qqbuddy *p, const qqbuddy *q) const{
		return p->number > q->number ;
	}
};
const buddy_comp buddy_comp_=buddy_comp();
struct searcher:public std::binary_function<qqbuddy*,uint,bool>{
	bool operator() (const qqbuddy *p,  uint v) const{
		return p->number ==v ;
	}
};
const searcher searcher_=searcher();
}
qqbuddy* buddy_get( qqclient* qq, uint number, int create )
{
//	if( create && number != qq->number ) return NULL;
	qqbuddy* b=NULL;
	if( !number )
		return NULL;
	QMutexLocker myql_(&qq->buddy_list_lock);	
	qqclient::buddy_list_type::iterator i=std::find_if(qq->buddy_list.begin(),qq->buddy_list.end(),std::bind2nd(searcher_,number));
	if(i!=qq->buddy_list.end()) b=*i;	
	else if(create ){
		b=new qqbuddy();
		b->number = number;
		qsnprintf( b->nickname,sizeof(b->nickname)-1, "%u", number );
		qq->buddy_list.push_back(b);		
	}
	return b;
}

void buddy_remove( qqclient* qq, uint number )
{	
	QMutexLocker myql_(&qq->buddy_list_lock);	
	qqclient::buddy_list_type::iterator i=std::find_if(qq->buddy_list.begin(),qq->buddy_list.end(),std::bind2nd(searcher_,number));
	if(i!=qq->buddy_list.end()) {
		qq->buddy_list.erase(i);
	}	
}

void buddy_sort_list( qqclient* qq )
{
	QMutexLocker myql_(&qq->buddy_list_lock);
	std::sort(qq->buddy_list.begin(),qq->buddy_list.end(),buddy_comp_);	
}


namespace {
	struct buddyoff_set:public std::unary_function<qqbuddy*,void>{
		void operator()(qqbuddy* q) const{
			q->status =  QQ_OFFLINE;
		}
	};
}
void buddy_set_all_off( qqclient* qq )
{
	QMutexLocker myql_(&qq->buddy_list_lock);
	std::for_each(qq->buddy_list.begin(),qq->buddy_list.end(),buddyoff_set());	
}

void buddy_update_list( qqclient* qq )
{
	prot_buddy_update_list( qq, 0 );
	prot_buddy_update_online( qq, 0 );
}

void buddy_update_info( qqclient* qq, qqbuddy* b )
{
	prot_buddy_get_info( qq, b->number );
}


int buddy_send_message( qqclient* qq, uint number, char* msg )
{
	prot_im_send_msg( qq, number, msg );
	return 0;
}

char* buddy_status_string( int st )
{
	switch( st ){
	case QQ_ONLINE:
		return "Online";
	case QQ_OFFLINE:
		return "Offline";
	case QQ_AWAY:
		return "Away";
	case QQ_HIDDEN:
		return "Hidden";
	case QQ_BUSY:
		return "Busy";
	case QQ_KILLME:
		return "KillMe";
	case QQ_QUIET:
		return "Quiet";
	default:
		return "Unknown";
	}
}

//buddy_put_event的函数在登录之后调用比较频繁，
//在获取好友列表，获取好友在线列表，获取好友签名，获取好友备注
void buddy_put_event( qqclient* qq )
{
	char *temp;
	qqbuddy* b;
	size_t tempsize=KB(128);
	temp=(char*)calloc(tempsize,1 );
	if( !temp ) return;
	qstrncpy( temp, "buddylist^$",tempsize-1 );
	QMutexLocker myql_(&qq->buddy_list_lock);	;
	struct in_addr addr;
	for(qqclient::buddy_list_type::iterator i=qq->buddy_list.begin();
		i!=qq->buddy_list.end();++i){
		b = *i;
		addr.s_addr = htonl( b->ip );
		qsnprintf( temp, tempsize-1,"%s%u\t%s\t%s\t%s\t%d\t%s\t%s\t%d^@", temp, b->number, buddy_status_string(b->status), b->nickname,
			b->signature, b->sex, inet_ntoa( addr ), b->alias, b->gid );
	}
	qqclient_put_event( qq, temp );
	free( temp );
}
